package cn.huiyunche.admin.security;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

import cn.huiyunche.base.service.framework.exception.AppError;
import cn.huiyunche.base.service.framework.utils.AppUtils;
import cn.huiyunche.base.service.vo.AdminUserVo;

/**
 * jwt认证过滤.
 * <p>
 * 当header中包含token时，通过本filter还原用户信息，供后续通过认证使用.
 *
 * @author zhaoshb
 * @since 0.0.1
 */
public class JwtAuthenicationFilter extends GenericFilterBean {

	public static final String HEADER_AUTHORIZATION = "Authorization";

	public static final String PREFIX_AUTHORIZATION = "Bearer ";

	private String secureKey = null;

	public JwtAuthenicationFilter(String secureKey) {
		this.secureKey = secureKey;
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest servletRequest = (HttpServletRequest) request;
		String token = servletRequest.getHeader(JwtAuthenicationFilter.HEADER_AUTHORIZATION);
		if ((token == null) || !token.startsWith(JwtAuthenicationFilter.PREFIX_AUTHORIZATION)) {
			chain.doFilter(servletRequest, response);
			return;
		}
		String jwt = token.substring(7);
		try {
			AdminUserVo user = JwtUtils.parseToken(jwt, this.getSecureKey());
			if(user!=null){
				Authentication authentication = this.createAuthentication(user);
				SecurityContextHolder.getContext().setAuthentication(authentication);
				chain.doFilter(servletRequest, response);
				SecurityContextHolder.getContext().setAuthentication(null);
			}
		} catch (Exception e) {
			e.printStackTrace();
			if(e.getCause().getMessage().startsWith("Form too large")){
				AppUtils.responseErrorJson(response, AppError.FormTooLarge);
			}
            AppUtils.responseErrorJson(response, AppError.AuthenticationInvalidError);
		}
	}

	private Authentication createAuthentication(AdminUserVo user) {
		return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
	}

	public String getSecureKey() {
		return this.secureKey;
	}

}
